<!DOCTYPE html>
<html lang="zh_cn">
<head>
          <title>来玩魔王的咚</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta charset="utf-8" />
        <!-- twitter card metadata -->
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="/images/mowang.png">
<meta name="twitter:site" content="">
<meta name="twitter:title" content="pytest（七）skip和xfail标记">
<meta name="twitter:description" content="<p>使用mark标记的skip和xfail这两个内置标记，处理预计会失败或是无法成功的测试。</p>">
        <!-- OG Tags -->
<meta property="og:url" content="/pytest-mark-skip-and-xfail.html"/>
<meta property="og:title" content="来玩魔王的咚 | pytest（七）skip和xfail标记" />
<meta property="og:description" content="<p>使用mark标记的skip和xfail这两个内置标记，处理预计会失败或是无法成功的测试。</p>" />
        <!-- favicon -->
        <link rel="icon" type="image/png" href="/images/mowang.png">
        <!-- moment.js for date formatting -->
        <script src="/theme/js/moment.js"></script>
        <!-- css -->
        <link rel="stylesheet" type="text/css" href="/theme/css/main.css" />
        <!-- 左边的menu，如果页面高度不够，就跟着滚动，否则文章分类显示不全 -->
        <link rel="stylesheet" type="text/css" href="/theme/css/mycss/menu.css" />
		<script>
			
                /*! grunt-grunticon Stylesheet Loader - v2.1.2 | https://github.com/filamentgroup/grunticon | (c) 2015 Scott Jehl, Filament Group, Inc. | MIT license. */
    
    (function(e){function t(t,n,r,o){"use strict";function a(){for(var e,n=0;u.length>n;n++)u[n].href&&u[n].href.indexOf(t)>-1&&(e=!0);e?i.media=r||"all":setTimeout(a)}var i=e.document.createElement("link"),l=n||e.document.getElementsByTagName("script")[0],u=e.document.styleSheets;return i.rel="stylesheet",i.href=t,i.media="only x",i.onload=o||null,l.parentNode.insertBefore(i,l),a(),i}var n=function(r,o){"use strict";if(r&&3===r.length){var a=e.navigator,i=e.Image,l=!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||e.opera&&-1===a.userAgent.indexOf("Chrome")||-1!==a.userAgent.indexOf("Series40")),u=new i;u.onerror=function(){n.method="png",n.href=r[2],t(r[2])},u.onload=function(){var e=1===u.width&&1===u.height,a=r[e&&l?0:e?1:2];n.method=e&&l?"svg":e?"datapng":"png",n.href=a,t(a,null,null,o)},u.src="",document.documentElement.className+=" grunticon"}};n.loadCSS=t,e.grunticon=n})(this);(function(e,t){"use strict";var n=t.document,r="grunticon:",o=function(e){if(n.attachEvent?"complete"===n.readyState:"loading"!==n.readyState)e();else{var t=!1;n.addEventListener("readystatechange",function(){t||(t=!0,e())},!1)}},a=function(e){return t.document.querySelector('link[href$="'+e+'"]')},c=function(e){var t,n,o,a,c,i,u={};if(t=e.sheet,!t)return u;n=t.cssRules?t.cssRules:t.rules;for(var l=0;n.length>l;l++)o=n[l].cssText,a=r+n[l].selectorText,c=o.split(");")[0].match(/US\-ASCII\,([^"']+)/),c&&c[1]&&(i=decodeURIComponent(c[1]),u[a]=i);return u},i=function(e){var t,o,a;o="data-grunticon-embed";for(var c in e)if(a=c.slice(r.length),t=n.querySelectorAll(a+"["+o+"]"),t.length)for(var i=0;t.length>i;i++)t[i].innerHTML=e[c],t[i].style.backgroundImage="none",t[i].removeAttribute(o);return t},u=function(t){"svg"===e.method&&o(function(){i(c(a(e.href))),"function"==typeof t&&t()})};e.embedIcons=i,e.getCSS=a,e.getIcons=c,e.ready=o,e.svgLoadedCallback=u,e.embedSVG=u})(grunticon,this);
                
                grunticon(["/theme/css/icons.data.svg.css", "/theme/css/icons.data.png.css", "/theme/css/icons.fallback.css"]);
            </script>
        <noscript><link href="/theme/css/icons.fallback.css" rel="stylesheet"></noscript>
        <!-- menu toggle javascript -->
        <script type="text/javascript">
            document.addEventListener("DOMContentLoaded", initMenu);
            
            function initMenu(){
                var menu = document.getElementById("menu");
                var menulink = document.getElementById("menu-link");
                menulink.addEventListener("click", function toggleMenu(){
                        window.event.preventDefault();
                        menulink.classList.toggle('active');
                        menu.classList.toggle('active');              
                    });
            };
        </script>
        <!-- 不蒜子 -->
        <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    <meta name="description" content="<p>使用mark标记的skip和xfail这两个内置标记，处理预计会失败或是无法成功的测试。</p>" />

    <meta name="tags" content="测试" />
  <!-- 替换部分base的样式，看文章时，要再宽一点，右边有很多空间可以撑开 -->
  <link rel="stylesheet" type="text/css" href="/theme/css/mycss/article.css" />

</head>
<body>
    <div role="banner" id="masthead">
        <header>
            <a href="/"><img src="/images/mowang.png" alt="McManus Logo"></a>
                <h1>来玩魔王的咚@骑士救兵</h1>
            <a href="#menu" id="menu-link">more stuff</a>
            <nav id="menu">
                <ul>
                        <li><a href="/tags">tags</a></li>
                            <li><a href="/category/cloud.html">Cloud</a></li>
                            <li><a href="/category/docker.html">Docker</a></li>
                            <li><a href="/category/go.html">Go</a></li>
                            <li><a href="/category/linux.html">Linux</a></li>
                            <li class="active"><a href="/category/python.html">Python</a></li>
                            <li><a href="/category/xue-xi-bi-ji.html">学习笔记</a></li>
                            <li><a href="/category/yun-wei-zi-dong-hua.html">运维自动化</a></li>
                </ul>
            </nav>
        </header>
    </div>
        <div class="page" role="main">
  <div class="article" role="article">
    <article>
        <footer>
            <a name="top"></a>
            <p>
              <time datetime=" 2022-03-29 21:04:00+08:00">
                <script>document.write(moment('2022-03-29 21:04:00+08:00').format('LL'));</script>
              </time>
              ~
              <time datetime=" 2022-03-29 21:04:00+08:00">
                <script>document.write(moment('2022-03-30 22:04:00+08:00').format('LL'));</script>
              </time>
            </p>
        </footer>
        <header>
          <h2>
            pytest（七）skip和xfail标记
          </h2>
        </header>
      <div class="content">
         <div class="toc">
<ul>
<li><a href="#shi-yong-biao-ji">使用标记</a><ul>
<li><a href="#bao-gao-zhai-yao-xin-xi">报告摘要信息</a></li>
</ul>
</li>
<li><a href="#skip-biao-ji">skip 标记</a><ul>
<li><a href="#skip-han-shu-tiao-chu">skip 函数跳出</a></li>
<li><a href="#que-shao-yi-lai-de-mo-kuai-er-tiao-guo">缺少依赖的模块而跳过</a></li>
<li><a href="#skipif-biao-ji">skipif 标记</a></li>
<li><a href="#gong-xiang-biao-ji">共享标记</a></li>
<li><a href="#lei-ji-bie-tian-jia-biao-ji">类级别添加标记</a></li>
<li><a href="#mo-kuai-ji-bie-tian-jia-biao-ji">模块级别添加标记</a></li>
<li><a href="#tiao-guo-wen-jian-huo-mu-lu">跳过文件或目录</a></li>
<li><a href="#xiao-jie">小结</a></li>
</ul>
</li>
<li><a href="#xfail-biao-ji">xfail 标记</a><ul>
<li><a href="#xfail-han-shu-biao-ji">xfail 函数标记</a></li>
<li><a href="#tiao-jian-can-shu">条件参数</a></li>
<li><a href="#raises-can-shu">raises 参数</a></li>
<li><a href="#run-can-shu">run 参数</a></li>
<li><a href="#strict-can-shu">strict 参数</a></li>
<li><a href="#hu-lve-xfail">忽略xfail</a></li>
<li><a href="#shi-li">示例</a></li>
</ul>
</li>
<li><a href="#can-shu-hua-ce-shi-tian-jia-biao-ji">参数化测试添加标记</a></li>
</ul>
</div>
<h3 id="shi-yong-biao-ji"><a class="toclink" href="#shi-yong-biao-ji">使用标记</a></h3>
<p>在入门篇里有介绍<a href="/pytest-getting-started.html#zi-ding-yi-mark-biao-ji">标记的基础知识</a>。本篇重点讲两个内置标记。  </p>
<p>有些测试有平台限制，在特定的平台上才会成功。有些测试预计会失败（比如功能还未完成）。可以为这些测试打上标记，pytest会处理这些标记，使得测试整体成功（不会对这些标记的测试报告失败）。  </p>
<p><strong>skip 标记</strong><br>
在某些情况下，期望跳过这个测试。比如，在非windows平台上跳过哪些仅限windows平台进行的测试。再比如，测试有依赖的外部资源，跳过依赖资源不可用的测试（如数据库）。  </p>
<p><strong>xfail 标记</strong><br>
由于一些原因，有些测试预计就会失败，可以加上标记。比如，对还未实现的功能写的测试，或者是一个还未修复的bug。</p>
<h4 id="bao-gao-zhai-yao-xin-xi"><a class="toclink" href="#bao-gao-zhai-yao-xin-xi">报告摘要信息</a></h4>
<p>pytest会分别统计和报告这些标记的测试，默认情况下，不会输出失败的详细情况，否则会和其他失败的测试报告造成混乱。<br>
使用-r参数，会报告额外的摘要信息（short test summary info）。-r参数后面要紧跟需要报告种类，具体看下面的例子：</p>
<div class="highlight"><pre><span></span><code>pytest -rfE   <span class="c1"># 默认设置，仅对(f)ailed, (E)rror做摘要报告</span>
pytest -rxXs  <span class="c1"># show extra info on xfailed, xpassed, and skipped tests</span>
pytest -rA    <span class="c1"># (A)ll，就是全部</span>
</code></pre></div>

<p>可用的选项是这些：(f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output, (a)ll except passed (p/P), or (A)ll。可以执行<code>pytest -h</code>在帮助信息中获取这些信息。<br>
报告摘要信息是测试报告中单独的一块统计报告，标题是short test summary info：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span>
<span class="k">def</span> <span class="nf">test_xpassed</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">1</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span>
<span class="k">def</span> <span class="nf">test_xfailed</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skip</span>
<span class="k">def</span> <span class="nf">test_skipped</span><span class="p">():</span>
    <span class="k">pass</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">pytest</span><span class="o">.</span><span class="n">main</span><span class="p">([</span><span class="vm">__file__</span><span class="p">,</span> <span class="s1">&#39;-rxXs&#39;</span><span class="p">])</span>

<span class="sd">&#39;&#39;&#39;</span>
<span class="sd">tests\test_short_summary.py Xxs                                                        [100%] </span>

<span class="sd">================================== short test summary info ================================== </span>
<span class="sd">XFAIL tests/test_short_summary.py::test_xfailed</span>
<span class="sd">XPASS tests/test_short_summary.py::test_xpassed</span>
<span class="sd">SKIPPED [1] tests\test_short_summary.py:18: unconditional skip</span>
<span class="sd">========================= 1 skipped, 1 xfailed, 1 xpassed in 0.06s ==========================</span>
<span class="sd">&#39;&#39;&#39;</span>
</code></pre></div>

<h3 id="skip-biao-ji"><a class="toclink" href="#skip-biao-ji">skip 标记</a></h3>
<p>使用装饰器标记，有一个可选的参数reason：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skip</span><span class="p">(</span><span class="n">reason</span><span class="o">=</span><span class="s2">&quot;no way of currently testing this&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_the_unknown_with_reason</span><span class="p">():</span>
    <span class="k">pass</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skip</span>  <span class="c1"># default: reason = &quot;unconditional skip&quot;</span>
<span class="k">def</span> <span class="nf">test_the_unknown</span><span class="p">():</span>
    <span class="k">pass</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">pytest</span><span class="o">.</span><span class="n">main</span><span class="p">([</span><span class="vm">__file__</span><span class="p">,</span> <span class="s1">&#39;-ra&#39;</span><span class="p">])</span>

<span class="sd">&#39;&#39;&#39;</span>
<span class="sd">================================= short test summary info ================================== </span>
<span class="sd">SKIPPED [1] tests\test_skipping.py:9: no way of currently testing this </span>
<span class="sd">SKIPPED [1] tests\test_skipping.py:13: unconditional skip</span>
<span class="sd">==================================== 2 skipped in 0.01s ====================================</span>
<span class="sd">&#39;&#39;&#39;</span>
</code></pre></div>

<p>reason会在报告摘要信息中显示，如果不写reason，默认是unconditional skip。  </p>
<h4 id="skip-han-shu-tiao-chu"><a class="toclink" href="#skip-han-shu-tiao-chu">skip 函数跳出</a></h4>
<p>在执行过程中，可以通过调用<code>pytest.skip(reason)</code>函数实现跳过。调用这个函数标记的skip与用mark标记的不同，是通过触发raise实现的，所以调用后不会再执行之后的代码（skip是整个标记的函数都不执行，而这里是执行到skip函数抛出异常为止）。  </p>
<p>下面是在函数中途跳出的例子，因为是直接在代码中调用，可以在前面加判断条件：</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">valid_config</span><span class="p">():</span>
        <span class="n">pytest</span><span class="o">.</span><span class="n">skip</span><span class="p">(</span><span class="s2">&quot;unsupported configuration&quot;</span><span class="p">)</span>
</code></pre></div>

<p>如果不填写原因，报告摘要信息中会显示Skipped。  </p>
<p>跳过整个模块：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">pytest</span>

<span class="k">if</span> <span class="ow">not</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;win&quot;</span><span class="p">):</span>
    <span class="n">pytest</span><span class="o">.</span><span class="n">skip</span><span class="p">(</span><span class="s2">&quot;skipping windows-only tests&quot;</span><span class="p">,</span> <span class="n">allow_module_level</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</code></pre></div>

<p>这是个判断是否是windows系统的例子，模块中任何位置出现这个语句，都会跳过整个模块的测试。整个模块只要符合条件都会跳过，这个方式设置的跳过会在测试发现阶段就有效果，不会发现有这个测试的模块。默认原因也是Skipped，这个似乎不重要，也不会报告出来。<br>
下面还有为整个模块标记的方法，标记模块中所有的测试。测试都能够被发现，但是会标记上skip。  </p>
<h4 id="que-shao-yi-lai-de-mo-kuai-er-tiao-guo"><a class="toclink" href="#que-shao-yi-lai-de-mo-kuai-er-tiao-guo">缺少依赖的模块而跳过</a></h4>
<p>导入模块，成功则完成了模块的导入。如果导入失败，则跳过当前模块的测试：</p>
<div class="highlight"><pre><span></span><code><span class="n">docutils</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">importorskip</span><span class="p">(</span><span class="s2">&quot;docutils&quot;</span><span class="p">)</span>
</code></pre></div>

<p>用这句语句代替模块的导入，导入成功那么就做赋值，相当于完成了模块的导入。  </p>
<p>还可以加上版本信息做更精确的判断：</p>
<div class="highlight"><pre><span></span><code><span class="n">docutils</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">importorskip</span><span class="p">(</span><span class="s2">&quot;modulename&quot;</span><span class="p">,</span> <span class="n">minversion</span><span class="o">=</span><span class="s2">&quot;0.3&quot;</span><span class="p">)</span>
</code></pre></div>

<p>版本信息是通过读取模块的<code>__version__</code>属性获取到的。  </p>
<p><code>pytest.importorskip</code>提供的应该是一个加了模块导入和模块版本判断的<code>pytest.skip</code>函数，效果应该是基本相同的，直接使用官方提供的轮子更方便。而且还多一个效果，如果模块可以导入，那么就直接完成了模块的导入。  </p>
<h4 id="skipif-biao-ji"><a class="toclink" href="#skipif-biao-ji">skipif 标记</a></h4>
<p>为标记添加条件判断，多一个条件表达式的判断。<br>
下面的例子是如果版本低于等于python3.6就会跳过：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">sys</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skipif</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">version_info</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span> <span class="n">reason</span><span class="o">=</span><span class="s2">&quot;requires python3.7 or higher&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">pass</span>
</code></pre></div>

<p>同样的，reason参数是可选的。  </p>
<p>可以叠加装饰器，添加多个标记。skipif装饰器可以使用多个，只要有一个标记为跳过，就会跳过该测试。  </p>
<h4 id="gong-xiang-biao-ji"><a class="toclink" href="#gong-xiang-biao-ji">共享标记</a></h4>
<p>将装饰器赋值给一个变量，可以在多个地方重复使用：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">mymodule</span>

<span class="c1"># 假设有个模块叫mymodule，这里需要版本至少是mymodule-1.1</span>
<span class="n">minversion</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skipif</span><span class="p">(</span>
    <span class="n">mymodule</span><span class="o">.</span><span class="n">__versioninfo__</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">reason</span><span class="o">=</span><span class="s2">&quot;at least mymodule-1.1 required&quot;</span>
<span class="p">)</span>

<span class="nd">@minversion</span>
<span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">pass</span>
</code></pre></div>

<p>在一个模块中定义好之后，可以跨模块使用的，在别的模块中导入minversion后一样用法。<br>
对于较大的测试项目，最好是在一个专门的文件中定义这些标记，在测试文件中导入并使用标记。  </p>
<h4 id="lei-ji-bie-tian-jia-biao-ji"><a class="toclink" href="#lei-ji-bie-tian-jia-biao-ji">类级别添加标记</a></h4>
<p>装饰器可以直接用在类上，类中的所有测试方法都会有标记：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skipif</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s2">&quot;win32&quot;</span><span class="p">,</span> <span class="n">reason</span><span class="o">=</span><span class="s2">&quot;does not run on windows&quot;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">TestPosixCalls</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">test_function</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="s2">&quot;will not be setup or run under &#39;win32&#39; platform&quot;</span>
</code></pre></div>

<h4 id="mo-kuai-ji-bie-tian-jia-biao-ji"><a class="toclink" href="#mo-kuai-ji-bie-tian-jia-biao-ji">模块级别添加标记</a></h4>
<p>模块级别不能用装饰器了，在模块中创建变量pytestmark并且赋值：</p>
<div class="highlight"><pre><span></span><code><span class="n">pytestmark</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skipif</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
</code></pre></div>

<p>模块级别添加多个标记：</p>
<div class="highlight"><pre><span></span><code><span class="n">pytestmark</span> <span class="o">=</span> <span class="p">[</span><span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skipif</span><span class="p">(</span><span class="kc">True</span><span class="p">),</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">webtest</span><span class="p">,</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">slowtest</span><span class="p">]</span>
</code></pre></div>

<h4 id="tiao-guo-wen-jian-huo-mu-lu"><a class="toclink" href="#tiao-guo-wen-jian-huo-mu-lu">跳过文件或目录</a></h4>
<p>skip无法支持这个需求，可以在测试发现层面实现：</p>
<ul>
<li>要把测试发现的规则写在配置文件中</li>
<li>文件或目录的名称要有一定的规则，这样方便做判断</li>
<li>如果有些条件要做动态的判读，那需要配置在<code>conftest.py</code>中</li>
</ul>
<p>留个官方文档的链接，不做具体的展开了：<br>
<a href="https://docs.pytest.org/en/7.0.x/example/pythoncollection.html#customizing-test-collection">https://docs.pytest.org/en/7.0.x/example/pythoncollection.html#customizing-test-collection</a>  </p>
<h4 id="xiao-jie"><a class="toclink" href="#xiao-jie">小结</a></h4>
<p>几个常用的模块级别添加标记的例子。  </p>
<p>无条件跳过所有测试：</p>
<div class="highlight"><pre><span></span><code><span class="n">pytestmark</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skip</span><span class="p">(</span><span class="s2">&quot;all tests still WIP&quot;</span><span class="p">)</span>
</code></pre></div>

<p>根据条件跳过所有测试：</p>
<div class="highlight"><pre><span></span><code><span class="n">pytestmark</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skipif</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s2">&quot;win32&quot;</span><span class="p">,</span> <span class="n">reason</span><span class="o">=</span><span class="s2">&quot;tests for linux only&quot;</span><span class="p">)</span>
</code></pre></div>

<p>导入模块或跳过测试：</p>
<div class="highlight"><pre><span></span><code><span class="n">pexpect</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">importorskip</span><span class="p">(</span><span class="s2">&quot;pexpect&quot;</span><span class="p">)</span>
</code></pre></div>

<p>替代模块的导入语句完成模块的导入，并且导入失败时能跳过当前模块中的测试。  </p>
<h3 id="xfail-biao-ji"><a class="toclink" href="#xfail-biao-ji">xfail 标记</a></h3>
<p>使用xfail标记预计会失败的测试。标记的测试会运行，但是不会报告测试失败。如果测试成功，会报告XPASS，如果测试失败，会报告XFAIL，会在报告摘要信息中报告：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span>
<span class="k">def</span> <span class="nf">test_xfail</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span>
<span class="k">def</span> <span class="nf">test_xsuccess</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">1</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="n">reason</span><span class="o">=</span><span class="s1">&#39;Some reason&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_xfail_reason</span><span class="p">():</span>
    <span class="k">pass</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">pytest</span><span class="o">.</span><span class="n">main</span><span class="p">([</span><span class="vm">__file__</span><span class="p">,</span> <span class="s1">&#39;-rxX&#39;</span><span class="p">])</span>

<span class="sd">&#39;&#39;&#39;</span>
<span class="sd">================================= short test summary info ================================= </span>
<span class="sd">XFAIL tests/test_xfail.py::test_xfail</span>
<span class="sd">XPASS tests/test_xfail.py::test_xsuccess</span>
<span class="sd">XPASS tests/test_xfail.py::test_xfail_reason Some reason</span>
<span class="sd">============================== 1 xfailed, 2 xpassed in 0.07s ==============================</span>
<span class="sd">&#39;&#39;&#39;</span>
</code></pre></div>

<p>同样有一个可选的reason参数可用于说明标记为xfail的动机，要使用关键字参数设置。不过没有建议要加上，并且不加reason也不会打印任何信息。  </p>
<h4 id="xfail-han-shu-biao-ji"><a class="toclink" href="#xfail-han-shu-biao-ji">xfail 函数标记</a></h4>
<p>使用<code>pytest.xfail</code>函数可以在测试中强制加上标记：</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">valid_config</span><span class="p">():</span>
        <span class="n">pytest</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="s2">&quot;failing configuration (but should work)&quot;</span><span class="p">)</span>
</code></pre></div>

<p>这里建议加上reason，reason是该函数唯一的参数，默认是空字符串。使用这个函数添加的标记会在报告摘要信息中新起一行缩进打印reason：</p>
<div class="highlight"><pre><span></span><code>================================= short test summary info ================================= 
XFAIL tests/test_xfail.py::test_xfail_noreason 
  reason:
XFAIL tests/test_xfail.py::test_xfail_reason 
  reason: failing configuration (but should work)
============================== 1 xfailed, 2 xpassed in 0.07s ==============================
</code></pre></div>

<p>调用这个函数与用mark标记的不同，是通过触发raise实现的，所以调用后不会再执行之后的代码。  </p>
<h4 id="tiao-jian-can-shu"><a class="toclink" href="#tiao-jian-can-shu">条件参数</a></h4>
<p>同skip和skipif不同，xfail可以直接加条件:</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s2">&quot;win32&quot;</span><span class="p">,</span> <span class="n">reason</span><span class="o">=</span><span class="s2">&quot;bug in a 3rd party library&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">pass</span>
</code></pre></div>

<p>此时的reason不是可选的，如果加了条件判断，那么也必须用关键字参数传一个原因。  </p>
<p>还可以直接使用字符串写条件表达式，和上面的效果一样：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="s1">&#39;sys.platform == &quot;win32&quot;&#39;</span><span class="p">,</span> <span class="n">reason</span><span class="o">=</span><span class="s2">&quot;bug in a 3rd party library&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">pass</span>
</code></pre></div>

<p>这样写不需要导入sys模块。另外，此时还能省略reason参数，此时reason就是表达式的值：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="s1">&#39;sys.platform == &quot;win32&quot;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">pass</span>
</code></pre></div>

<h4 id="raises-can-shu"><a class="toclink" href="#raises-can-shu">raises 参数</a></h4>
<p>设置了raises参数，如果测试失败，不再是在报告摘要信息中报告，而是向普通的测试失败那样报告。如果是成功，那么是在报告摘要信息中报告XPASS。也就是将XFAIL的摘要报告替换成测试失败的详细报告：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="n">raises</span><span class="o">=</span><span class="ne">RuntimeError</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_function</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>
</code></pre></div>

<p>这里的参数名称是raises复数，可以接收多个异常。将异常写在元组中传给raises参数。  </p>
<h4 id="run-can-shu"><a class="toclink" href="#run-can-shu">run 参数</a></h4>
<p>默认行为是执行测试，成功则报告XPASS，失败报告XFAIL。添加参数<code>run=False</code>后，则不会执行测试直接标记为XFAIL，并且会填上原因<code>reason: [NOTRUN]</code>：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="n">run</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_run0</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>

<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="n">run</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_run1</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">1</span>

<span class="sd">&#39;&#39;&#39;</span>
<span class="sd">============================ short test summary info ============================ </span>
<span class="sd">XFAIL tests/test_xfail.py::test_run0</span>
<span class="sd">  reason: [NOTRUN]</span>
<span class="sd">XFAIL tests/test_xfail.py::test_run1</span>
<span class="sd">  reason: [NOTRUN]</span>
<span class="sd">============================== 2 xfailed in 0.10s ===============================</span>
<span class="sd">&#39;&#39;&#39;</span>
</code></pre></div>

<p>这个方式对于那些运行会导致异常、崩溃的函数很有用。先设置为NOTRUN，之后可以再调查修复。  </p>
<h4 id="strict-can-shu"><a class="toclink" href="#strict-can-shu">strict 参数</a></h4>
<p>添加关键字参数<code>strict=True</code>会改变XPASS的行为。由于xfail标记的是预计会失败的测试，如果测试通过就是和预期不符。<br>
如果<code>strict=True</code>，XPASS的测试会被标记为失败：</p>
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="n">strict</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_strict</span><span class="p">():</span>
    <span class="k">pass</span>

<span class="sd">&#39;&#39;&#39;</span>
<span class="sd">tests\test_xfail.py F                                                                   [100%] </span>

<span class="sd">========================================== FAILURES ========================================== </span>
<span class="sd">________________________________________ test_strict _________________________________________</span>
<span class="sd">[XPASS(strict)]</span>
<span class="sd">===================================== 1 failed in 0.02s ====================================== </span>
<span class="sd">&#39;&#39;&#39;</span>
</code></pre></div>

<p>还可以在全局修改这个默认行为，修改ini配置文件：</p>
<div class="highlight"><pre><span></span><code><span class="k">[pytest]</span><span class="w"></span>
<span class="na">xfail_strict</span><span class="o">=</span><span class="s">true</span><span class="w"></span>
</code></pre></div>

<h4 id="hu-lve-xfail"><a class="toclink" href="#hu-lve-xfail">忽略xfail</a></h4>
<p>使用命令行参数<code>--runxfail</code>忽略：</p>
<div class="highlight"><pre><span></span><code>pytest --runxfail
</code></pre></div>

<p>参数的说明如下：</p>
<div class="highlight"><pre><span></span><code>--runxfail            report the results of xfail tests as if they were not marked
</code></pre></div>

<p>也就是完全忽略xfail标记，和没有添加标记一样进行处理。  </p>
<h4 id="shi-li"><a class="toclink" href="#shi-li">示例</a></h4>
<p>下面是一组测试示例，包含常用的几种用法：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="n">xfail</span> <span class="o">=</span> <span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span>


<span class="nd">@xfail</span>
<span class="k">def</span> <span class="nf">test_hello</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>


<span class="nd">@xfail</span><span class="p">(</span><span class="n">run</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_hello2</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>


<span class="nd">@xfail</span><span class="p">(</span><span class="s2">&quot;hasattr(os, &#39;sep&#39;)&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_hello3</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>


<span class="nd">@xfail</span><span class="p">(</span><span class="n">reason</span><span class="o">=</span><span class="s2">&quot;bug 110&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_hello4</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>


<span class="nd">@xfail</span><span class="p">(</span><span class="s1">&#39;pytest.__version__[0] != &quot;17&quot;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_hello5</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">0</span>


<span class="k">def</span> <span class="nf">test_hello6</span><span class="p">():</span>
    <span class="n">pytest</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="s2">&quot;reason&quot;</span><span class="p">)</span>


<span class="nd">@xfail</span><span class="p">(</span><span class="n">raises</span><span class="o">=</span><span class="ne">IndexError</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_hello7</span><span class="p">():</span>
    <span class="n">x</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

<span class="sd">&#39;&#39;&#39;</span>
<span class="sd">! pytest -rx xfail_demo.py</span>
<span class="sd">=========================== test session starts ============================</span>
<span class="sd">platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-1.x.y</span>
<span class="sd">cachedir: $PYTHON_PREFIX/.pytest_cache</span>
<span class="sd">rootdir: $REGENDOC_TMPDIR/example</span>
<span class="sd">collected 7 items</span>

<span class="sd">xfail_demo.py xxxxxxx                                                [100%]</span>

<span class="sd">========================= short test summary info ==========================</span>
<span class="sd">XFAIL xfail_demo.py::test_hello</span>
<span class="sd">XFAIL xfail_demo.py::test_hello2</span>
<span class="sd">  reason: [NOTRUN]</span>
<span class="sd">XFAIL xfail_demo.py::test_hello3</span>
<span class="sd">  condition: hasattr(os, &#39;sep&#39;)</span>
<span class="sd">XFAIL xfail_demo.py::test_hello4</span>
<span class="sd">  bug 110</span>
<span class="sd">XFAIL xfail_demo.py::test_hello5</span>
<span class="sd">  condition: pytest.__version__[0] != &quot;17&quot;</span>
<span class="sd">XFAIL xfail_demo.py::test_hello6</span>
<span class="sd">  reason: reason</span>
<span class="sd">XFAIL xfail_demo.py::test_hello7</span>
<span class="sd">============================ 7 xfailed in 0.12s ============================</span>
<span class="sd">&#39;&#39;&#39;</span>
</code></pre></div>

<h3 id="can-shu-hua-ce-shi-tian-jia-biao-ji"><a class="toclink" href="#can-shu-hua-ce-shi-tian-jia-biao-ji">参数化测试添加标记</a></h3>
<p>在参数化测试时，可以为每个测试实例添加标记：</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">pytest</span>


<span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span>
    <span class="p">(</span><span class="s2">&quot;n&quot;</span><span class="p">,</span> <span class="s2">&quot;expected&quot;</span><span class="p">),</span>
    <span class="p">[</span>
        <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
        <span class="n">pytest</span><span class="o">.</span><span class="n">param</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">marks</span><span class="o">=</span><span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">),</span>
        <span class="n">pytest</span><span class="o">.</span><span class="n">param</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">marks</span><span class="o">=</span><span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">xfail</span><span class="p">(</span><span class="n">reason</span><span class="o">=</span><span class="s2">&quot;some bug&quot;</span><span class="p">)),</span>
        <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span>
        <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span>
        <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span>
        <span class="n">pytest</span><span class="o">.</span><span class="n">param</span><span class="p">(</span>
            <span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="n">marks</span><span class="o">=</span><span class="n">pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">skipif</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">version_info</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">reason</span><span class="o">=</span><span class="s2">&quot;py2k&quot;</span><span class="p">)</span>
        <span class="p">),</span>
    <span class="p">],</span>
<span class="p">)</span>
<span class="k">def</span> <span class="nf">test_increment</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
    <span class="k">assert</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="n">expected</span>
</code></pre></div>
      </div>
      <div class="back-to-top">
        <a href="/">HOME</a>
        <a href="#top">TOP</a>
      </div>
    </article>
  </div>
<!-- end article -->
<!-- 页面往下滚动一段之后才会显示TOC -->
<script>
  window.onscroll = function() {
    var tocbox = document.getElementsByClassName('toc')[0];
    var osTop = document.documentElement.scrollTop || document.body.scrollTop;
    var osWidth = document.documentElement.scrollWidth || document.body.scrollWidth;
    // console.log(osTop)
    if (osTop>300 && osWidth>865) {
      tocbox.style.display = "block"
    }
    if (osTop<300 || osWidth<865) {
      tocbox.style.display = "none"
    }
  }
</script>
                <footer>
                    <div class="icons">
                    </div>
                    <span id="busuanzi_container_page_pv" style="padding: 10px">本文阅读量<span id="busuanzi_value_page_pv"></span>次</span>
                    <span id="busuanzi_container_site_pv" style="padding: 10px">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
                    <span id="busuanzi_container_site_uv" style="padding: 10px">本站总访客数<span id="busuanzi_value_site_uv"></span>人</span>
                    <p>© <script>document.write(moment().format('YYYY'));</script> 749B</p>
                </footer>
        </div>
</body>
</html>